package GameServer

import (
	. "PBMessage"
	. "SGNet"
	proto "github.com/golang/protobuf/proto"
	log "misc/seelog"
	"time"
	"utils/uuid"

	. "GameLogic/Scene"
)

const (
	SCENETICK_TIME  = 3000
	SCENETICK_Logic = 1000000000 / 60
)

type GameScene struct {
	SceneID        int64
	sceneTickTime  int64
	sceneTickLogic int64
	clientPlayers  []*ClientPlayer
	LogicScene     *Scene
	ModuleInfo
}

func NewGameScene() *GameScene {
	RetGameScene := &GameScene{}
	RetGameScene.ModuleInfo.New()
	RetGameScene.SceneID = uuid.Int64UUID()
	RetGameScene.LogicScene = NewScene()
	return RetGameScene
}
func (this *GameScene) Init(clientPlayers []*ClientPlayer, infos []*ReadRoomPlayer) {
	//add Handler
	this.AddHandler(PBID_CS_SceneTick, func(msg *Message) {})
	this.AddCommandHandler(CMD_ClientLost, this.CMD_ClientLost)
	//add ScenePlayer
	this.clientPlayers = clientPlayers
	for i := 0; i < len(this.clientPlayers); i++ {
		this.clientPlayers[i].Sess.UserData = this.clientPlayers[i]
		this.clientPlayers[i].PlayerState = PLAYERSTATE_SCENE

		enterScene := &SC_EnterGameScene{}
		roomSize := GetGameHall().RoomSize
		enterScene.CampList0 = infos[:roomSize/2]
		enterScene.CampList1 = infos[roomSize/2:]
		this.clientPlayers[i].RunScene = this
		this.clientPlayers[i].Sess.SendPacket(PBID_SC_EnterGameScene, enterScene)
	}

	//Add Trigger Handler
	this.AddHandler(PBID_CS_PushUnitCommand, this.LogicScene.HandlerPushUnitCommand)
	//Add GameTrigger Player

	for ci := 0; ci < len(this.clientPlayers); ci++ {
		gp := &GamePlayer{}
		gp.Id = ci
		gp.Sess = this.clientPlayers[ci].Sess
		gp.UserName = this.clientPlayers[ci].UserName
		gp.SelectUnitName = infos[ci].GetSelectId()
		this.LogicScene.AddGamePlayer(gp)
	}
	this.LogicScene.Init()
	this.LogicScene.OnLoad()
	go this.loop()
}

func (this *GameScene) loop() {
	var lastSceneTickTime int64 = time.Now().UnixNano()
	var subSceneTickTime int64
	for {
		this.ModuleInfo.processMessage()
		//3S tick
		this.sceneTickTime++
		if this.sceneTickTime >= SCENETICK_TIME {
			this.SceneTick()
			this.sceneTickTime = 0
		}
		//Logic tick 0.016s 60FPS
		subSceneTickTime = time.Now().UnixNano() - lastSceneTickTime
		this.sceneTickLogic += subSceneTickTime
		if this.sceneTickLogic >= SCENETICK_Logic {
			this.TickLogic()
			this.sceneTickLogic = 0
		}
		lastSceneTickTime = time.Now().UnixNano()
		time.Sleep(time.Millisecond)
	}
}

func (this *GameScene) SceneTick() {
	tick := &SC_SceneTick{}
	tick.ServerTime = proto.Int64(time.Now().UnixNano())
	for i := 0; i < len(this.clientPlayers); i++ {
		if this.clientPlayers[i] != nil {
			this.clientPlayers[i].Sess.SendPacket(PBID_SC_SceneTick, tick)
		}
	}
}

func (this *GameScene) TickLogic() {
	this.LogicScene.Update()
}

func (this *GameScene) RemovePlayer(userName string) {
	for i := 0; i < len(this.clientPlayers); i++ {
		if this.clientPlayers[i] != nil && this.clientPlayers[i].UserName == userName {
			this.clientPlayers[i] = nil
		}
	}
}

func (this *GameScene) CMD_ClientLost(msg *Message) {
	log.Info("Scene 移除玩家")
	sess := msg.Param["Sess"].(*Session)
	clientPlayer := sess.UserData.(*ClientPlayer)
	this.RemovePlayer(clientPlayer.UserName)
	this.LogicScene.GamePlayerLost(clientPlayer.UserName)
}
